#pragma once

#include "../Main/Standard.h"
#include "../Utility/HashString.h"
#include "../Math/Matrix4x4.h"
#include "../Console/ConsoleWindow.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
/// <Summary>	ICollideAble  </Summary>
/// 
/// <purpose>	Base interface class for all collidable types </purpose>
////////////////////////////////////////////////////////////////////////////////////////////////////

class ICollideAble
{
public:

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Default constructor. </Summary>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	ICollideAble() { }

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Virtual Destructor </Summary>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ~ICollideAble(void) = 0 { }

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Gets the collision type </Summary>
	///
	/// <Return>	The collision type </Return>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual const HashString& GetCollisionType() const = 0;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Transforms this object by a matrix </Summary>
	///
	/// <Param name="transform">	The transform matrix	</Param>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void Transform(const Matrix4x4& transform) { }

protected:

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Prints this object to the console </Summary>
	///
	/// <Param name="out">	The console window </Param>
	///
	/// <Return>	The console window </Return>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ConsoleWindow& Print(ConsoleWindow& out) const { return out; }

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Utility to allow any collideable object to print to the console </Summary>
	///
	/// <Param name="out">		 	The console window </Param>
	/// <Param name="collidable">	The collidable object </Param>
	///
	/// <Return>	The console window </Return>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	friend ConsoleWindow& operator<<(ConsoleWindow& out, const ICollideAble& collidable)
	{
		return collidable.Print(out);
	}
};

////////////////////////////////////////////////////////////////////////////////////////////////////
/// <Summary>	IBoundingCollideAble  </Summary>
/// 
/// <purpose>	Base interface class for all collidable types with a bounding volume </purpose>
////////////////////////////////////////////////////////////////////////////////////////////////////

class IBoundingCollideAble : public ICollideAble
{
public:

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Default constructor. </Summary>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	IBoundingCollideAble() { }

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Virtual Destructor </Summary>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual ~IBoundingCollideAble(void) = 0 { }

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Builds the bounding volume from a set of points </Summary>
	///
	/// <Param name="verts">   	The verts </Param>
	/// <Param name="numVerts">	Number of verts </Param>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void Build(const Vector3* verts, unsigned int numVerts) { };

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	
	/// 	Builds the bound volume from two other bounding volumes of the same type 
	/// </Summary>
	///
	/// <Param name="bounds1">	The first bounds </Param>
	/// <Param name="bounds2">	The second bounds </Param>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void Build(const IBoundingCollideAble* bounds1, const IBoundingCollideAble* bounds2) { };

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <Summary>	Translates this object </Summary>
	///
	/// <Param name="translation">	The translation vector	</Param>
	////////////////////////////////////////////////////////////////////////////////////////////////////
	virtual void Translate(const Vector3& translation) { }
};